#############################################################################
# Copyright (c) 2009 Dmitry Grushin <dgrushin@gmail.com>.
#
# This file is part of clupower (cluster power manager utility)
#
# Clupower is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Clupower is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Clupower.  If not, see <http://www.gnu.org/licenses/>.
#
# Contributors:
#    Dmitry Grushin <dgrushin@gmail.com> - initial API and implementation
#############################################################################

require 'settings'
require 'commands'

class CPTest

  # Executes test commands
  def test
    test_scheduler && test_nodes && sleep_node
  end
  
  private

  def print_ok(ok)
    if ok
      puts "ok"
    else
      puts "failed"
    end
    return ok
  end

  def print_err(err)
    puts "  Error details: " + err.get_trace
  end

  def test_scheduler
    print "Checking connection with scheduler ... "
    nodes = Cmd.instance.get_free_nodes
    tasks = Cmd.instance.get_queue
    print " #{nodes.size} free nodes, #{tasks.size} tasks in queue. "
    return print_ok(true)
  rescue CPRuntimeError => e
    print_ok(false)
    print_err(e)
    return false
  end

  def test_nodes
    if Settings.instance.get('SIMULATE')
      puts "Warning: running test with SIMULATE mode active. " +
        "Nodes will not be powered off and on."
    end
    print "Checking ssh connection with available nodes ... "
    ok = true
    for node in Cmd.instance.get_status_nodes("free", "job-exclusive")
      # TODO: can check if necessary commands work on nodes
      Cmd.instance.execute_on_node(node, "echo")
    end
    return print_ok(true)
  rescue CPRuntimeError => e
    print_ok(false)
    print_err(e)
    return false
  end

  def sleep_node
    node = Cmd.instance.get_free_nodes.first
    print "Trying to put one node (#{node}) into sleep: "
    if node
      start = Time.now.to_i
      print "power off command issued, now wait for node shutdown ..."
      STDOUT.flush
      Cmd.instance.node_off(node)
      sleep_total = 0
      while Cmd.instance.chassis_powered?(node) && sleep_total < 600
        sleep_total += sleep(3)
      end
      off_time_sec = Time.now.to_i - start
      if(sleep_total >= 600)
        print " timeout (600s) exceeded. "
        return false
      end
      print_ok(true)
      start = Time.now.to_i
      print "Trying to wake up the node: power on command issued, wait for node free status ..."
      STDOUT.flush
      Cmd.instance.node_on(node)
      sleep_total = 0
      until Cmd.instance.get_free_nodes.include?(node) || sleep_total >= 600
        sleep_total += sleep(3)
      end
      on_time_sec = Time.now.to_i - start
      if(sleep_total >= 600)
        print " timeout (600s) exceeded. "
        return false
      end
      print_ok(true)
      puts "Measured timeout (seconds): node off - #{off_time_sec}, node on - #{on_time_sec}." +
        " Update configuration file."
      return true
    else
      print "No free nodes. "
    end
    return print_ok(false)
  rescue CPRuntimeError => e
    Cmd.instance.torque_node_online(node)
    print_ok(false)
    print_err(e)
    return false
  end
end
